package com.huaxin.hxmoduleworkorder.service.impl;

import com.huaxin.feignclient.device.models.ElectricalRoom;
import com.huaxin.feignclient.device.models.SwitchCabinet;
import com.huaxin.feignclient.system.SystemClient;
import com.huaxin.feignclient.system.models.ElectricianArchives;
import com.huaxin.hxmoduleworkorder.common.PdfGenerator;
import com.huaxin.hxmoduleworkorder.dto.ResponseCode;
import com.huaxin.hxmoduleworkorder.dto.ResponseResult;
import com.huaxin.hxmoduleworkorder.dto.response.InspectionReportDTO;
import com.huaxin.hxmoduleworkorder.dto.response.InspectionReportGroupByCabinetDTO;
import com.huaxin.hxmoduleworkorder.dto.response.InspectionReportGroupByRoomDTO;
import com.huaxin.hxmoduleworkorder.dto.response.InspectionReportOrderItemDTO;
import com.huaxin.hxmoduleworkorder.feignclients.DeviceFeignService;
import com.huaxin.hxmoduleworkorder.mapping.InspectionOrderItemMapping;
import com.huaxin.hxmoduleworkorder.models.InspectionOrder;
import com.huaxin.hxmoduleworkorder.models.InspectionOrderItem;
import com.huaxin.hxmoduleworkorder.service.InspectionOrderItemService;
import com.huaxin.hxmoduleworkorder.service.InspectionOrderService;
import com.huaxin.hxmoduleworkorder.service.InspectionReportService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class InspectionReportServiceImpl implements InspectionReportService {
    private final SystemClient systemClient;
    private final PdfGenerator pdfGenerator;
    private final AiSuggestionServiceImpl aiSuggestionService;
    private final InspectionOrderItemService inspectionOrderItemService;
    private final InspectionOrderService inspectionOrderService;
    private final AIGenerateService aiGenerateService;
    private final InspectionOrderItemMapping inspectionOrderItemMapping;
    private final DeviceFeignService deviceFeignService;

    @Override
    public byte[] generateReport(String inspectionId, String customerId) {
        // 1. 根据 inspectionId 查询数据库中的巡检记录
        ResponseResult<InspectionOrder> inspectionOrder = inspectionOrderService.get(inspectionId);
        if (inspectionOrder.getCode() != ResponseCode.SUCCESS.getCode() || inspectionOrder.getData() == null) {
            return null;
        }
        ResponseResult<List<InspectionOrderItem>> result = inspectionOrderItemService.listByOrder(inspectionId, customerId, null);
        if (result.getCode() != ResponseCode.SUCCESS.getCode() || result.getData() == null) {
            return null;
        }
        com.huaxin.feignclient.models.ResponseResult<ElectricianArchives> electricianArchives = systemClient.getElectricianArchivesDetail(inspectionOrder.getData().getAssignedElectricianId());
        if (electricianArchives.getCode() != ResponseCode.SUCCESS.getCode() || electricianArchives.getData() == null) {
            return null;
        }
        List<InspectionOrderItem> items = result.getData();
        Optional<InspectionOrderItem> earliestItem = items.stream()
                .min(Comparator.comparing(InspectionOrderItem::getCreatedAt));

        // 2. 构建 DTO
        InspectionReportDTO report = new InspectionReportDTO();
        if (earliestItem.isPresent()) {
            InspectionOrderItem firstItem = earliestItem.get();
            report.setInspectionTime(firstItem.getCreatedAt());
        }
        report.setOrderNumber(inspectionOrder.getData().getId());
        report.setElectricianName(electricianArchives.getData().getRealName());
        report.setElectricianPhone(electricianArchives.getData().getPhone());
        report.setTitle("巡查报告");

        List<InspectionReportOrderItemDTO> itemsDTO = inspectionOrderItemMapping.toInspectionReportOrderItemDTOList(items);
        List<String> roomIds = items.stream().map(InspectionOrderItem::getRoomId).distinct().toList();
        List<String> cabinetIds = items.stream().map(InspectionOrderItem::getCabinetId).distinct().toList();
        List<ElectricalRoom> rooms = deviceFeignService.electricianRoomListByIds(roomIds);
        List<SwitchCabinet> cabinets = deviceFeignService.cabinetListByIds(cabinetIds);

        // 按 roomId 分组 -> 按 cabinetId 分组
        Map<String, Map<String, List<InspectionReportOrderItemDTO>>> grouped = itemsDTO.stream()
                .collect(
                        Collectors.groupingBy(
                                InspectionReportOrderItemDTO::getRoomId,
                                Collectors.groupingBy(InspectionReportOrderItemDTO::getCabinetId)
                        )
                );

        // 转换为嵌套 DTO 结构
        List<InspectionReportGroupByRoomDTO> groupedDTOs = grouped.entrySet().stream().map(roomEntry -> {
            InspectionReportGroupByRoomDTO roomDTO = new InspectionReportGroupByRoomDTO();
            roomDTO.setRoomId(roomEntry.getKey());
            roomDTO.setRoomName(rooms.stream()
                    .filter(r -> r.getId().equals(roomEntry.getKey()))
                    .map(ElectricalRoom::getRoomName)
                    .findFirst().orElse("未知配电房"));

            List<InspectionReportGroupByCabinetDTO> cabinetDTOs = roomEntry.getValue().entrySet().stream()
                    .map(cabEntry -> {
                        String cabinetId = cabEntry.getKey();
                        List<InspectionReportOrderItemDTO> itemDTOS = cabEntry.getValue();

                        String cabinetName = cabinets.stream()
                                .filter(c -> c.getId().equals(cabinetId))
                                .map(SwitchCabinet::getCabinetName)
                                .findFirst()
                                .orElse("未知配电箱");

                        return new InspectionReportGroupByCabinetDTO(cabinetId, cabinetName, itemDTOS);
                    })
                    .toList();

            roomDTO.setCabinets(cabinetDTOs);
            return roomDTO;
        }).toList();

        // 设置到 report
        report.setGroupedItems(groupedDTOs);

        // 3. 生成 AI 建议
        report.setAiSuggestion(aiGenerateService.generateAiSuggestion(items));

        // 4. 生成 PDF
        try {
            return pdfGenerator.generatePdf(report);
        } catch (Exception e) {
            throw new RuntimeException("PDF 生成失败", e);
        }
    }
}
